#include "listhandel.h"
#include"kernelList/kernellist.h"
#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
typedef struct listHead{
  pthread_mutex_t mutex;
  int DataSzie;
  ListCore list;
}listHead;
typedef struct listData{
  pthread_mutex_t mutex;
  void *data;
  ListCore list;
}listData;

HEAD initList(int DATASzie)
{

  listHead *ptr=NULL;
  if(DATASzie==0)
    {
      goto __DATASZIE__;
    }
  ptr=(listHead *)malloc(sizeof(listHead));
  if(ptr==NULL)
    {
      goto __LISTHEAD_MALLOC_;
    }
  ptr->DataSzie=DATASzie;
  INIT_LIST_HEAD(&(ptr->list));
  if(pthread_mutex_init(&(ptr->mutex),NULL)<0)
    {
      goto LISTHEAD_MUTEX_INIT;
    }
  return ptr;
__DATASZIE__:
  return ptr;
__LISTHEAD_MALLOC_:
  free(ptr);
  return ptr;
LISTHEAD_MUTEX_INIT:
  free(ptr);
  return ptr;
}

int addData(HEAD head, DATA data)
{
  listHead *tmp=NULL;
  listData *ptr=NULL;
  if(head==NULL)
    goto ADD_HEAD_NULL;
  if(data==NULL)
    goto ADD_DATA_NULL;
  tmp=head;
  ptr=(listData *)malloc(sizeof(listData));
  memset(ptr,0,sizeof(*ptr));
  if(ptr==NULL)
    goto ADD_MALLOC_NULL;
  INIT_LIST_HEAD(&(ptr->list));
  if(pthread_mutex_init(&(ptr->mutex),NULL)<0)
    goto ADD_MUTEX_INIT;
  ptr->data=malloc(tmp->DataSzie);
  if(ptr->data==NULL)
    goto ADD_PTR_DATA_NULL;
  memcpy(ptr->data,data,tmp->DataSzie);
  list_add(&ptr->list,&tmp->list);
  return 0;
ADD_HEAD_NULL:
  return -1;
ADD_DATA_NULL:
  return -2;
ADD_MALLOC_NULL:
  return -3;
ADD_MUTEX_INIT:
  free(ptr);
  return -4;
ADD_PTR_DATA_NULL:
  free(ptr);
  return -5;

}

int delData(HEAD head, operation fun, const void *arg)
{
  if(head==NULL || fun == NULL || arg==NULL)
    goto DEL_DATA_ARGUMENT;
  listHead *tmp=head;
  listData *data=NULL;
  listData *tmplist=NULL;

  list_for_each_entry_safe(data,tmplist,&(tmp->list),list)
  {
    pthread_mutex_lock(&data->mutex);
    if(fun(data->data,arg)==0)
      {
        list_del(&(data->list));
        pthread_mutex_unlock(&data->mutex);
        free(data->data);
        free(data);
        return 0;
      }
    pthread_mutex_unlock(&data->mutex);

  }
  return -1;
DEL_DATA_ARGUMENT:
  return -2;

}

int repData(HEAD head, operation fun, const void *arg, const DATA Data)
{
  if(head==NULL || fun == NULL || arg==NULL || Data==NULL)
    goto REP_DATA_ARGUMENT;
  listHead *tmp=head;
  listData *data=NULL;
  listData *tmplist=NULL;

  list_for_each_entry_safe(data,tmplist,&(tmp->list),list)
  {
    pthread_mutex_lock(&data->mutex);
    if(fun(data->data,arg)==0)
      {
        memcpy(data->data,Data,tmp->DataSzie);
        pthread_mutex_unlock(&data->mutex);
        return 0;
      }
    pthread_mutex_unlock(&data->mutex);
  }
  return -1;
REP_DATA_ARGUMENT:
  return -2;
}

int fidData(HEAD head, operation fun, const void *arg, DATA Data)
{
  if(head==NULL || fun == NULL || arg==NULL || Data==NULL)
    goto FID_DATA_ARGUMENT;
  listHead *tmp=head;
  listData *data=NULL;
  listData *tmplist=NULL;

  list_for_each_entry_safe(data,tmplist,&(tmp->list),list)
  {
    pthread_mutex_lock(&data->mutex);
    if(fun(data->data,arg)==0)
      {
        list_del(&data->list);
        memcpy(Data,data->data,tmp->DataSzie);
        pthread_mutex_unlock(&data->mutex);
        return 0;
      }
    pthread_mutex_unlock(&data->mutex);
  }
  return -1;
FID_DATA_ARGUMENT:
  return -2;
}

void freeList(HEAD head)
{
  if(head==NULL)
    return ;
  listHead *tmp=head;
  listData *data=NULL;
  listData *tmplist=NULL;
  list_for_each_entry_safe(data,tmplist,&(tmp->list),list)
  {
    pthread_mutex_lock(&data->mutex);
        list_del(&data->list);
    pthread_mutex_unlock(&data->mutex);
    free(data->data);
    free(data);
  }
}

int outData(HEAD head, operation fun)
{
  if(head==NULL || fun == NULL)
    goto OUT_DATA_ARGUMENT;
  listHead *tmp=head;
  listData *data=NULL;
  listData *tmplist=NULL;

  list_for_each_entry_safe(data,tmplist,&(tmp->list),list)
  {
    pthread_mutex_lock(&data->mutex);
    fun(data->data,NULL);
    pthread_mutex_unlock(&data->mutex);
  }
  return 0;
OUT_DATA_ARGUMENT:
  return -2;
}
